package com.datagateway.controller;

import com.datagateway.component.DataEncryptionManager;
import com.datagateway.component.DataTransmissionEncryptionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据加密控制器
 * 提供数据加密和解密的API接口
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@RestController
@RequestMapping("/api/encryption")
public class DataEncryptionController {

    @Autowired
    private DataEncryptionManager dataEncryptionManager;

    @Autowired
    private DataTransmissionEncryptionManager transmissionEncryptionManager;

    /**
     * 获取加密统计信息
     * 
     * @return 统计信息
     */
    @GetMapping("/statistics")
    public Map<String, Object> getEncryptionStatistics() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            DataEncryptionManager.EncryptionStatistics statistics = dataEncryptionManager.getStatistics();
            
            result.put("success", true);
            result.put("statistics", statistics);
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取加密统计信息失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 获取传输加密统计信息
     * 
     * @return 统计信息
     */
    @GetMapping("/transmission/statistics")
    public Map<String, Object> getTransmissionEncryptionStatistics() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            DataTransmissionEncryptionManager.TransmissionEncryptionStatistics statistics = 
                transmissionEncryptionManager.getStatistics();
            
            result.put("success", true);
            result.put("statistics", statistics);
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取传输加密统计信息失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 加密数据
     * 
     * @param request 加密请求
     * @return 加密结果
     */
    @PostMapping("/encrypt")
    public Map<String, Object> encryptData(@RequestBody EncryptionRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            String keyAlias = request.getKeyAlias() != null ? request.getKeyAlias() : "default";
            DataEncryptionManager.EncryptedData encryptedData = 
                dataEncryptionManager.encryptData(request.getData(), keyAlias);
            
            if (encryptedData.isEncrypted()) {
                result.put("success", true);
                result.put("encryptedData", encryptedData);
                result.put("message", "数据加密成功");
                result.put("timestamp", System.currentTimeMillis());
            } else {
                result.put("success", false);
                result.put("message", "数据加密失败");
                result.put("timestamp", System.currentTimeMillis());
            }
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "数据加密失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 解密数据
     * 
     * @param request 解密请求
     * @return 解密结果
     */
    @PostMapping("/decrypt")
    public Map<String, Object> decryptData(@RequestBody DecryptionRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            DataEncryptionManager.EncryptedData encryptedData = new DataEncryptionManager.EncryptedData(
                request.getData(),
                request.getIv(),
                request.getKeyAlias(),
                request.getAlgorithm(),
                true
            );
            
            String decryptedData = dataEncryptionManager.decryptData(encryptedData);
            
            result.put("success", true);
            result.put("decryptedData", decryptedData);
            result.put("message", "数据解密成功");
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "数据解密失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 加密敏感字段
     * 
     * @param request 敏感字段加密请求
     * @return 加密结果
     */
    @PostMapping("/encrypt/fields")
    public Map<String, Object> encryptSensitiveFields(@RequestBody SensitiveFieldsEncryptionRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            Map<String, Object> encryptedData = 
                dataEncryptionManager.encryptSensitiveFields(request.getData());
            
            result.put("success", true);
            result.put("encryptedData", encryptedData);
            result.put("message", "敏感字段加密成功");
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "敏感字段加密失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 解密敏感字段
     * 
     * @param request 敏感字段解密请求
     * @return 解密结果
     */
    @PostMapping("/decrypt/fields")
    public Map<String, Object> decryptSensitiveFields(@RequestBody SensitiveFieldsDecryptionRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            Map<String, Object> decryptedData = 
                dataEncryptionManager.decryptSensitiveFields(request.getData());
            
            result.put("success", true);
            result.put("decryptedData", decryptedData);
            result.put("message", "敏感字段解密成功");
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "敏感字段解密失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 生成新的加密密钥
     * 
     * @param request 密钥生成请求
     * @return 生成结果
     */
    @PostMapping("/key/generate")
    public Map<String, Object> generateNewKey(@RequestBody KeyGenerationRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = dataEncryptionManager.generateNewKey(request.getKeyAlias());
            
            if (success) {
                result.put("success", true);
                result.put("keyAlias", request.getKeyAlias());
                result.put("message", "加密密钥生成成功");
                result.put("timestamp", System.currentTimeMillis());
            } else {
                result.put("success", false);
                result.put("message", "加密密钥生成失败");
                result.put("timestamp", System.currentTimeMillis());
            }
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "加密密钥生成失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 添加敏感字段
     * 
     * @param request 敏感字段添加请求
     * @return 添加结果
     */
    @PostMapping("/sensitive-field/add")
    public Map<String, Object> addSensitiveField(@RequestBody SensitiveFieldRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            DataEncryptionManager.EncryptionRule rule = new DataEncryptionManager.EncryptionRule(
                request.getKeyAlias(),
                request.getAlgorithm(),
                request.isRequired()
            );
            
            dataEncryptionManager.addSensitiveField(request.getFieldName(), rule);
            
            result.put("success", true);
            result.put("fieldName", request.getFieldName());
            result.put("rule", rule);
            result.put("message", "敏感字段添加成功");
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "敏感字段添加失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 移除敏感字段
     * 
     * @param fieldName 字段名
     * @return 移除结果
     */
    @DeleteMapping("/sensitive-field/{fieldName}")
    public Map<String, Object> removeSensitiveField(@PathVariable String fieldName) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            dataEncryptionManager.removeSensitiveField(fieldName);
            
            result.put("success", true);
            result.put("fieldName", fieldName);
            result.put("message", "敏感字段移除成功");
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "敏感字段移除失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 建立安全传输通道
     * 
     * @param request 传输通道建立请求
     * @return 建立结果
     */
    @PostMapping("/transmission/channel/establish")
    public Map<String, Object> establishSecureChannel(@RequestBody ChannelEstablishRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            DataTransmissionEncryptionManager.ChannelEncryptionConfig config = 
                new DataTransmissionEncryptionManager.ChannelEncryptionConfig(
                    request.getChannelType(),
                    request.isEncryptionEnabled(),
                    request.getSslProtocol(),
                    request.getCipherSuite(),
                    request.getConnectionTimeout(),
                    request.getReadTimeout()
                );
            
            boolean success = transmissionEncryptionManager.establishSecureChannel(
                request.getChannelId(), config);
            
            if (success) {
                result.put("success", true);
                result.put("channelId", request.getChannelId());
                result.put("config", config);
                result.put("message", "安全传输通道建立成功");
                result.put("timestamp", System.currentTimeMillis());
            } else {
                result.put("success", false);
                result.put("message", "安全传输通道建立失败");
                result.put("timestamp", System.currentTimeMillis());
            }
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "安全传输通道建立失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 关闭安全传输通道
     * 
     * @param channelId 通道ID
     * @return 关闭结果
     */
    @DeleteMapping("/transmission/channel/{channelId}")
    public Map<String, Object> closeSecureChannel(@PathVariable String channelId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = transmissionEncryptionManager.closeSecureChannel(channelId);
            
            if (success) {
                result.put("success", true);
                result.put("channelId", channelId);
                result.put("message", "安全传输通道关闭成功");
                result.put("timestamp", System.currentTimeMillis());
            } else {
                result.put("success", false);
                result.put("message", "安全传输通道关闭失败");
                result.put("timestamp", System.currentTimeMillis());
            }
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "安全传输通道关闭失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 获取传输通道状态
     * 
     * @param channelId 通道ID
     * @return 通道状态
     */
    @GetMapping("/transmission/channel/{channelId}")
    public Map<String, Object> getChannelStatus(@PathVariable String channelId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            DataTransmissionEncryptionManager.TransmissionChannel channel = 
                transmissionEncryptionManager.getChannelStatus(channelId);
            
            if (channel != null) {
                result.put("success", true);
                result.put("channel", channel);
                result.put("timestamp", System.currentTimeMillis());
            } else {
                result.put("success", false);
                result.put("message", "传输通道不存在");
                result.put("timestamp", System.currentTimeMillis());
            }
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取传输通道状态失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 获取所有传输通道状态
     * 
     * @return 通道状态列表
     */
    @GetMapping("/transmission/channels")
    public Map<String, Object> getAllChannelStatus() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<DataTransmissionEncryptionManager.TransmissionChannel> channels = 
                transmissionEncryptionManager.getAllChannelStatus();
            
            result.put("success", true);
            result.put("channels", channels);
            result.put("channelCount", channels.size());
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取传输通道状态失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 验证传输数据完整性
     * 
     * @param request 完整性验证请求
     * @return 验证结果
     */
    @PostMapping("/transmission/verify")
    public Map<String, Object> verifyTransmissionIntegrity(@RequestBody IntegrityVerificationRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean isValid = transmissionEncryptionManager.verifyTransmissionIntegrity(
                request.getData(), request.getChecksum());
            
            result.put("success", true);
            result.put("isValid", isValid);
            result.put("message", isValid ? "数据完整性验证通过" : "数据完整性验证失败");
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "数据完整性验证失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 设置加密配置
     * 
     * @param request 配置请求
     * @return 操作结果
     */
    @PostMapping("/config")
    public Map<String, Object> setEncryptionConfig(@RequestBody EncryptionConfigRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            dataEncryptionManager.setEncryptionConfig(
                request.isEnabled(),
                request.getAlgorithm(),
                request.getKeySize(),
                request.getGcmIvLength(),
                request.getGcmTagLength()
            );
            
            result.put("success", true);
            result.put("enabled", request.isEnabled());
            result.put("algorithm", request.getAlgorithm());
            result.put("keySize", request.getKeySize());
            result.put("gcmIvLength", request.getGcmIvLength());
            result.put("gcmTagLength", request.getGcmTagLength());
            result.put("message", "加密配置已更新");
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "设置加密配置失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    /**
     * 设置传输加密配置
     * 
     * @param request 配置请求
     * @return 操作结果
     */
    @PostMapping("/transmission/config")
    public Map<String, Object> setTransmissionConfig(@RequestBody TransmissionConfigRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            transmissionEncryptionManager.setTransmissionConfig(
                request.isEnabled(),
                request.getSslProtocol(),
                request.getCipherSuite(),
                request.isVerificationEnabled(),
                request.getConnectionTimeout(),
                request.getReadTimeout()
            );
            
            result.put("success", true);
            result.put("enabled", request.isEnabled());
            result.put("sslProtocol", request.getSslProtocol());
            result.put("cipherSuite", request.getCipherSuite());
            result.put("verificationEnabled", request.isVerificationEnabled());
            result.put("connectionTimeout", request.getConnectionTimeout());
            result.put("readTimeout", request.getReadTimeout());
            result.put("message", "传输加密配置已更新");
            result.put("timestamp", System.currentTimeMillis());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "设置传输加密配置失败: " + e.getMessage());
            result.put("timestamp", System.currentTimeMillis());
        }
        
        return result;
    }

    // 请求类定义
    public static class EncryptionRequest {
        private String data;
        private String keyAlias;

        public String getData() { return data; }
        public void setData(String data) { this.data = data; }
        public String getKeyAlias() { return keyAlias; }
        public void setKeyAlias(String keyAlias) { this.keyAlias = keyAlias; }
    }

    public static class DecryptionRequest {
        private String data;
        private String iv;
        private String keyAlias;
        private String algorithm;

        public String getData() { return data; }
        public void setData(String data) { this.data = data; }
        public String getIv() { return iv; }
        public void setIv(String iv) { this.iv = iv; }
        public String getKeyAlias() { return keyAlias; }
        public void setKeyAlias(String keyAlias) { this.keyAlias = keyAlias; }
        public String getAlgorithm() { return algorithm; }
        public void setAlgorithm(String algorithm) { this.algorithm = algorithm; }
    }

    public static class SensitiveFieldsEncryptionRequest {
        private Map<String, Object> data;

        public Map<String, Object> getData() { return data; }
        public void setData(Map<String, Object> data) { this.data = data; }
    }

    public static class SensitiveFieldsDecryptionRequest {
        private Map<String, Object> data;

        public Map<String, Object> getData() { return data; }
        public void setData(Map<String, Object> data) { this.data = data; }
    }

    public static class KeyGenerationRequest {
        private String keyAlias;

        public String getKeyAlias() { return keyAlias; }
        public void setKeyAlias(String keyAlias) { this.keyAlias = keyAlias; }
    }

    public static class SensitiveFieldRequest {
        private String fieldName;
        private String keyAlias;
        private String algorithm;
        private boolean required;

        public String getFieldName() { return fieldName; }
        public void setFieldName(String fieldName) { this.fieldName = fieldName; }
        public String getKeyAlias() { return keyAlias; }
        public void setKeyAlias(String keyAlias) { this.keyAlias = keyAlias; }
        public String getAlgorithm() { return algorithm; }
        public void setAlgorithm(String algorithm) { this.algorithm = algorithm; }
        public boolean isRequired() { return required; }
        public void setRequired(boolean required) { this.required = required; }
    }

    public static class ChannelEstablishRequest {
        private String channelId;
        private String channelType;
        private boolean encryptionEnabled;
        private String sslProtocol;
        private String cipherSuite;
        private int connectionTimeout;
        private int readTimeout;

        public String getChannelId() { return channelId; }
        public void setChannelId(String channelId) { this.channelId = channelId; }
        public String getChannelType() { return channelType; }
        public void setChannelType(String channelType) { this.channelType = channelType; }
        public boolean isEncryptionEnabled() { return encryptionEnabled; }
        public void setEncryptionEnabled(boolean encryptionEnabled) { this.encryptionEnabled = encryptionEnabled; }
        public String getSslProtocol() { return sslProtocol; }
        public void setSslProtocol(String sslProtocol) { this.sslProtocol = sslProtocol; }
        public String getCipherSuite() { return cipherSuite; }
        public void setCipherSuite(String cipherSuite) { this.cipherSuite = cipherSuite; }
        public int getConnectionTimeout() { return connectionTimeout; }
        public void setConnectionTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; }
        public int getReadTimeout() { return readTimeout; }
        public void setReadTimeout(int readTimeout) { this.readTimeout = readTimeout; }
    }

    public static class IntegrityVerificationRequest {
        private String data;
        private String checksum;

        public String getData() { return data; }
        public void setData(String data) { this.data = data; }
        public String getChecksum() { return checksum; }
        public void setChecksum(String checksum) { this.checksum = checksum; }
    }

    public static class EncryptionConfigRequest {
        private boolean enabled = true;
        private String algorithm = "AES/GCM/NoPadding";
        private int keySize = 256;
        private int gcmIvLength = 12;
        private int gcmTagLength = 128;

        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        public String getAlgorithm() { return algorithm; }
        public void setAlgorithm(String algorithm) { this.algorithm = algorithm; }
        public int getKeySize() { return keySize; }
        public void setKeySize(int keySize) { this.keySize = keySize; }
        public int getGcmIvLength() { return gcmIvLength; }
        public void setGcmIvLength(int gcmIvLength) { this.gcmIvLength = gcmIvLength; }
        public int getGcmTagLength() { return gcmTagLength; }
        public void setGcmTagLength(int gcmTagLength) { this.gcmTagLength = gcmTagLength; }
    }

    public static class TransmissionConfigRequest {
        private boolean enabled = true;
        private String sslProtocol = "TLSv1.3";
        private String cipherSuite = "TLS_AES_256_GCM_SHA384";
        private boolean verificationEnabled = true;
        private int connectionTimeout = 30000;
        private int readTimeout = 60000;

        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        public String getSslProtocol() { return sslProtocol; }
        public void setSslProtocol(String sslProtocol) { this.sslProtocol = sslProtocol; }
        public String getCipherSuite() { return cipherSuite; }
        public void setCipherSuite(String cipherSuite) { this.cipherSuite = cipherSuite; }
        public boolean isVerificationEnabled() { return verificationEnabled; }
        public void setVerificationEnabled(boolean verificationEnabled) { this.verificationEnabled = verificationEnabled; }
        public int getConnectionTimeout() { return connectionTimeout; }
        public void setConnectionTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; }
        public int getReadTimeout() { return readTimeout; }
        public void setReadTimeout(int readTimeout) { this.readTimeout = readTimeout; }
    }
}
